//
//  NSObject+YKSwizzle.m
//  YKKit
//
//  Created by 马洪伟 on 16/1/12.
//  Copyright © 2016年 悦康动力（北京）科技有限公司. All rights reserved.
//

#import "NSObject+YKSwizzle.h"
#import <objc/runtime.h>
#import <objc/message.h>

void SetNSError(NSError *__autoreleasing *error, NSString *format) {
    if (!error || !format) {
        return;
    }
    *error = [NSError errorWithDomain:@"NSCocoaErrorDomain" code:-1 userInfo:@{NSLocalizedDescriptionKey : format}];
}

@implementation NSObject (YKSwizzle)
+ (BOOL)yk_SwizzleMethod:(SEL)originalMethodSEL withMethod:(SEL)alternateMethodSEL error:(NSError *__autoreleasing *)error {
    Class cl = self;
    
    Method originalMethod = class_getInstanceMethod(cl, originalMethodSEL);
    if (!originalMethod) {
        SetNSError(error, [NSString stringWithFormat:@"original instance method 【%@】 not found for class 【%@】",NSStringFromSelector(originalMethodSEL),NSStringFromClass(cl)]);
        return NO;
    }
    
    Method alternateMethod = class_getInstanceMethod(cl, alternateMethodSEL);
    if (!alternateMethod) {
        SetNSError(error, [NSString stringWithFormat:@"alternate instance method 【%@】 not found for class 【%@】",NSStringFromSelector(alternateMethodSEL),NSStringFromClass(cl)]);
        return NO;
    }
    
//    class_addMethod(cl, originalMethodSEL, class_getMethodImplementation(cl, originalMethodSEL), method_getTypeEncoding(originalMethod));
//    class_addMethod(cl, alternateMethodSEL, class_getMethodImplementation(cl, alternateMethodSEL), method_getTypeEncoding(alternateMethod));
    
    method_exchangeImplementations(originalMethod, alternateMethod);
    
    return YES;
}
+ (BOOL)yk_SwizzleClassMethod:(SEL)originalMethodSEL withMethod:(SEL)alternateMethodSEL error:(NSError *__autoreleasing *)error {
    Class cl = self;
    
    Method originalMethod = class_getClassMethod(cl, originalMethodSEL);
    if (!originalMethod) {
        SetNSError(error, [NSString stringWithFormat:@"original class method 【%@】 not found for class 【%@】",NSStringFromSelector(originalMethodSEL),NSStringFromClass(cl)]);
        return NO;
    }
    
    Method alternateMethod = class_getClassMethod(cl, alternateMethodSEL);
    if (!alternateMethod) {
        SetNSError(error, [NSString stringWithFormat:@"alternate class method 【%@】 not found for class 【%@】",NSStringFromSelector(alternateMethodSEL),NSStringFromClass(cl)]);
        return NO;
    }
    
//    class_addMethod(cl, originalMethodSEL, class_getMethodImplementation(cl, originalMethodSEL), method_getTypeEncoding(originalMethod));
//    class_addMethod(cl, alternateMethodSEL, class_getMethodImplementation(cl, alternateMethodSEL), method_getTypeEncoding(alternateMethod));
    
    method_exchangeImplementations(originalMethod, alternateMethod);
    
    return YES;
}
@end
